#ifndef __TCP_SERVER_HPP__
#define __TCP_SERVER_HPP__

#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include "./ThreadPool/ThreadPool.hpp"

#define SIZE 1024

// 其他版本下的server
//  static void server(int sock, std::string serIp, uint16_t serPort)
//  {
//      char buff[SIZE];
//      while (true)
//      {
//          memset(buff, 0, sizeof(buff));
//          ssize_t s = recv(sock, buff, sizeof(buff) - 1, 0);
//          if (s > 0)
//          {
//              buff[s]='\0';
//              printf("host:%s port:%d# %s\n",serIp.c_str(),serPort,buff);
//              send(sock,buff,sizeof(buff),0);
//          }
//          else if (s == 0)
//          {
//              logMessage(WARNING, "aside close\n");
//              break;
//          }
//          else
//          {
//              // 读取失败
//              logMessage(ERROR, "recv:%s\n", errno, strerror(errno));
//              break;
//          }
//      }
//      close(sock);
//  }

// 单例线程池下的server
static void server(int sock, std::string cliIp, uint16_t cliPort, std::string name)
{
    char buff[SIZE];
    while (true)
    {
        memset(buff, 0, sizeof(buff));
        ssize_t s = recv(sock, buff, sizeof(buff) - 1, 0);
        if (s > 0)
        {
            buff[s] = '\0';
            printf("[%s]host:%s port:%d# %s\n", name.c_str(), cliIp.c_str(), cliPort, buff);
            send(sock, buff, s, 0);
        }
        else if (s == 0)
        {
            // 对端关闭
            logMessage(WARNING, "aside close\n");
            break;
        }
        else
        {
            // 读取失败
            logMessage(ERROR, "recv:%s\n", strerror(errno));
            break;
        }
    }
    close(sock);
}

static void englishServer(int sock, std::string cliIp, uint16_t cliPort, std::string name)
{
    char buff[SIZE];
    static std::unordered_map<std::string, std::string> dict = {{"apple", "苹果"}, {"dictionary", "字典"}, {"human", "人类"}};
    while (true)
    {
        memset(buff, 0, sizeof(buff));
        ssize_t s = recv(sock, buff, SIZE - 1, 0);
        if (s > 0)
        {
            buff[s] = '\0';
            auto iter = dict.find(buff);
            std::string result;
            if (iter == dict.end())
            {
                result = "I don't know!";
            }
            else
            {
                result = iter->second;
            }

            send(sock, result.c_str(), result.size(), 0);
        }
        else if (s == 0)
        {
            // 对端关闭
            logMessage(WARNING, "host:%s port:%d close\n", cliIp.c_str(), cliPort);
            break;
        }
        else
        {
            // 读取出错
            logMessage(ERROR, "recv:%s\n", strerror(errno));
            break;
        }
    }
    close(sock);
}

// 多线程版使用
//  struct ThreadData
//  {
//      ThreadData(uint16_t port,std::string ip,int sock)
//          :_port(port)
//          ,_ip(ip)
//          ,_sock(sock)
//      {}

//     ~ThreadData()
//     {
//         close(_sock);
//     }

//     uint16_t _port;
//     std::string _ip;
//     int _sock;
// };

class TCPServer
{
private:
    static const int backlog = 20;

private:
    // 多线程版使用
    //  static void* routinue(void* args)
    //  {
    //      //为了让主线程不等待，进行线程分离
    //      pthread_detach(pthread_self());
    //      ThreadData* td=(ThreadData*)args;
    //      server(td->_sock,td->_ip,td->_port);
    //      delete td;
    //      return nullptr;
    //  }

public:
    TCPServer(uint16_t port, std::string ip = "")
        : _port(port), _ip(ip), _listenSock(-1)
    {
    }

    void initServer()
    {
        // 获取套接字
        _listenSock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenSock < 0)
        {
            logMessage(FATAL, "socket:%s\n", strerror(errno));
            exit(2);
        }

        // bind
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());

        if (bind(_listenSock, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(FATAL, "bind:%s\n", strerror(errno));
            exit(3);
        }

        logMessage(NORMAL, "initServer success\n");

        ThreadPool<Task>::getThreadPool()->start();
        logMessage(NORMAL, "ThreadPool start success\n");
    }

    void start()
    {
        while (true)
        {
            // listen
            if (listen(_listenSock, backlog) < 0)
            {
                logMessage(WARNING, "listen:%s\n", strerror(errno));
                continue;
            }
            logMessage(NORMAL, "listen success\n");

            // accept
            struct sockaddr_in peer;
            memset(&peer, 0, sizeof(peer));
            socklen_t len = sizeof(peer);
            int sock = accept(_listenSock, (struct sockaddr *)&peer, &len);
            if (sock < 0)
            {
                logMessage(WARNING, "accept:%s\n", strerror(errno));
                continue;
            }

            // 查看链接的ip和port
            std::string cliIp = inet_ntoa(peer.sin_addr);
            uint16_t cliPort = ntohs(peer.sin_port);
            logMessage(NORMAL, "host:%s port:%d accpet success\n", cliIp.c_str(), cliPort);

            // 执行服务

            // version 1---单进程版
            //  server(sock, serIp, serPort);

            // version 2---多进程版
            //  signal(SIGCHLD,SIG_IGN);

            // pid_t pid=fork();
            // if(pid==0)
            // {
            //     //child
            //     close(_listenSock);
            //     server(sock,serIp,serPort);
            //     exit(3);
            // }
            // else if(pid<0)
            // {
            //     logMessage(ERROR,"%d:%s\n",errno,strerror(errno));
            //     continue;
            // }
            // close(sock);

            // version 2.1---多进程非信号版
            //  pid_t pid=fork();
            //  if(pid==0)
            //  {
            //      //child
            //      if(fork()>0)
            //      {
            //          exit(0);
            //      }

            //     //走到这里就是孙子进程在运行了
            //     close(_listenSock);
            //     server(sock,serIp,serPort);
            //     exit(0);
            // }
            // else if(pid<0)
            // {
            //     logMessage(ERROR,"fock:%s\n",strerror(errno));
            //     continue;
            // }

            // close(sock);
            // waitpid(-1,nullptr,0);

            // version 3---多线程版
            //  pthread_t tid;
            //  ThreadData* td=new ThreadData(serPort,serIp,sock);
            //  pthread_create(&tid,nullptr,routinue,(void*)td);

            // version 4---单例线程池版
            //  Task task(cliPort,cliIp,sock,server);
            //  ThreadPool<Task>::getThreadPool()->push(task);

            Task task(cliPort,cliIp,sock,englishServer);
            ThreadPool<Task>::getThreadPool()->push(task);
        }
    }

    ~TCPServer()
    {
        close(_listenSock);
    }

private:
    uint16_t _port;
    std::string _ip;
    int _listenSock;
};

#endif